import { isBetween } from '../../util/math';

export class GameMath {
  static readonly PRECISION = 6;
  static readonly EXP_10_PRECISION = 10 ** GameMath.PRECISION;
  static readonly SIN_TABLE: number[] = [
    0, 0.004848117819001859, 0.009696121685978396, 0.014543897651582654,
    0.01939133177182437, 0.024238310110748135, 0.0290847187431114,
    0.03393044375706223, 0.03877537125681671, 0.043619387365336,
    0.04846237822700296, 0.05330423001029823, 0.05814482891047582,
    0.06298406115223795, 0.06782181299240934, 0.0726579707226106,
    0.07749242067193093, 0.08232504920959989, 0.08715574274765817,
    0.09198438774362744, 0.09681087070317909, 0.10163507818280187,
    0.10645689679246824, 0.11127621319829964, 0.11609291412523022,
    0.12090688635966935, 0.12571801675216268, 0.13052619222005157,
    0.13533129975013108, 0.14013322640130627, 0.14493185930724672,
    0.1497270856790396, 0.15451879280784048, 0.15930686806752256,
    0.16409119891732396, 0.1688716729044928, 0.17364817766693033,
    0.17842060093583212, 0.18318883053832663, 0.18795275440011186,
    0.19271226054808968, 0.19746723711299752, 0.20221757233203794,
    0.20696315455150538, 0.2117038722294107, 0.21643961393810288,
    0.22117026836688775, 0.2258957243246448, 0.23061587074244014,
    0.2353305966761376, 0.24003979130900588, 0.2447433439543238,
    0.24944114405798126, 0.25413308120107847, 0.25881904510252074,
    0.26349892562161076, 0.2681726127606373, 0.272839996667461,
    0.27750096763809573, 0.28215541611928774, 0.2868032327110902,
    0.29144430816943495, 0.2960785334086999, 0.3007057995042731,
    0.3053259976951131, 0.30993901938630514, 0.31454475615161365,
    0.31914309973603083, 0.323733942058321, 0.328317175213561,
    0.33289269147567657, 0.3374603832999741, 0.3420201433256687,
    0.34657186437840753, 0.3511154394727888, 0.3556507618148765,
    0.3601777248047104, 0.36469622203881186, 0.3692061473126844,
    0.3737073946233105, 0.3781998581716425, 0.3826834323650898,
    0.3871580118200006, 0.3916234913641391, 0.3960797660391568,
    0.4005267311030606, 0.4049642820326736, 0.4093923145260926,
    0.4138107245051391, 0.4182194081178064, 0.42261826174069944,
    0.4270071819814715, 0.4313860656812534, 0.4357548099170794,
    0.4401133120043048, 0.44446146949902104, 0.4487991802004621,
    0.4531263421534082, 0.4574428536505808, 0.4617486132350339,
    0.46604351970253877, 0.4703274721039625, 0.4746003697476404,
    0.4788621122017435, 0.4831125992966384, 0.48735173112724234,
    0.49157940805537054, 0.49579553071207916, 0.49999999999999994,
    0.5041927170956704, 0.5083735834518556, 0.5125425007998652,
    0.5166993711518628, 0.5208440968031697, 0.5249765803345602,
    0.5290967246145525, 0.5332044328016912, 0.5372996083468239,
    0.5413821549953696, 0.5454519767895825, 0.549508978070806,
    0.5535530634817223, 0.5575841379685927, 0.5616021067834929,
    0.5656068754865385, 0.5695983499481065, 0.573576436351046,
    0.5775410411928851, 0.5814920712880266, 0.5854294337699405,
    0.5893530360933448, 0.593262786036382, 0.5971585917027862,
    0.6010403615240428, 0.6049080042615417, 0.6087614290087207,
    0.6126005451932028, 0.6164252625789254, 0.62023549126826,
    0.6240311417041269, 0.6278121246720986, 0.6315783513024975,
    0.6353297330724851, 0.6390661818081416, 0.6427876096865393,
    0.6464939292378065, 0.6501850533471834, 0.6538608952570697,
    0.6575213685690636, 0.6611663872459932, 0.6647958656139378,
    0.6684097183642425, 0.6720078605555224, 0.6755902076156601,
    0.6791566753437932, 0.6827071799122926, 0.6862416378687335,
    0.6897599661378576, 0.6932620820235242, 0.696747903210655,
    0.7002173477671685, 0.7036703341459059, 0.7071067811865475,
    0.710526608117521, 0.713929734557899, 0.7173160805192894,
    0.7206855664077146, 0.7240381130254825, 0.7273736415730487,
    0.7306920736508674, 0.7339933312612352, 0.7372773368101241,
    0.7405440131090046, 0.7437932833766612, 0.747025071240996,
    0.7502393007408245, 0.7534358963276606, 0.7566147828674927,
    0.7597758856425494, 0.7629191303530553, 0.766044443118978,
    0.7691517504817651, 0.7722409794060692, 0.7753120572814658,
    0.7783649119241599, 0.7813994715786823, 0.7844156649195757,
    0.7874134210530723, 0.7903926695187593, 0.7933533402912352,
    0.7962953637817558, 0.7992186708398696, 0.8021231927550437,
    0.8050088612582783, 0.8078756085237111, 0.8107233671702122,
    0.8135520702629676, 0.8163616513150519, 0.8191520442889918,
    0.821923183598318, 0.8246750041091067, 0.8274074411415104,
    0.8301204304712788, 0.8328139083312671, 0.8354878114129364,
    0.8381420768678404, 0.8407766423091032, 0.8433914458128856,
    0.845986425919841, 0.848561521636559, 0.8511166724369997,
    0.8536518182639162, 0.8561668995302665, 0.8586618571206132,
    0.8611366323925137, 0.8635911671778986, 0.8660254037844386,
    0.8684392849969005, 0.870832754078492, 0.8732057547721958,
    0.8755582313020908, 0.8778901283746645, 0.8802013911801111,
    0.8824919653936212, 0.8847617971766577, 0.8870108331782216,
    0.8892390205361062, 0.8914463068781385, 0.8936326403234122,
    0.8957979694835052, 0.8979422434636881, 0.9000654118641211,
    0.9021674247810376, 0.9042482328079179, 0.9063077870366499,
    0.9083460390586793, 0.9103629409661466, 0.9123584453530141,
    0.9143325053161794, 0.9162850744565779, 0.918216106880274,
    0.9201255571995389, 0.9220133805339185, 0.9238795325112867,
    0.9257239692688903, 0.9275466474543786, 0.9293475242268224,
    0.9311265572577219, 0.9328837047320004, 0.9346189253489884,
    0.9363321783233931, 0.9380234233862578, 0.9396926207859083,
    0.9413397312888874, 0.942964716180876, 0.9445675372676047,
    0.9461481568757504, 0.947706537853822, 0.9492426435730339,
    0.9507564379281666, 0.9522478853384153, 0.9537169507482269,
    0.955163599628123, 0.9565877979755122, 0.9579895123154889,
    0.9593687097016201, 0.9607253577167205, 0.9620594244736131,
    0.9633708786158803, 0.9646596893185995, 0.9659258262890683,
    0.9671692597675166, 0.9683899605278059, 0.969587899878116,
    0.97076304966162, 0.9719153822571454, 0.9730448705798238,
    0.9741514880817275, 0.9752352087524931, 0.9762960071199334,
    0.9773338582506355, 0.9783487377505475, 0.9793406217655515,
    0.980309486982024, 0.9812553106273847, 0.9821780704706308,
    0.98307774482286, 0.9839543125377807, 0.984807753012208,
    0.9856380461865492, 0.9864451725452739, 0.987229113117374,
    0.987989849476809, 0.9887273637429388, 0.9894416385809445,
    0.9901326572022359, 0.9908004033648453, 0.9914448613738104,
    0.9920660160815423, 0.9926638528881819, 0.993238357741943,
    0.9937895171394426, 0.9943173181260184, 0.9948217482960331,
    0.9953027957931658, 0.9957604493106914, 0.9961946980917455,
    0.9966055319295779, 0.996992941167792, 0.9973569167005722,
    0.9976974499728977, 0.9980145329807433, 0.9983081582712682,
    0.9985783189429907, 0.9988250086459504, 0.9990482215818578,
    0.99924795250423, 0.9994241967185149, 0.9995769500822006,
    0.9997062090049132, 0.9998119704485015, 0.9998942319271075,
    0.9999529915072262, 0.9999882478077495, 1, 0.9999882478077495,
    0.9999529915072262, 0.9998942319271075, 0.9998119704485015,
    0.9997062090049132, 0.9995769500822006, 0.9994241967185149,
    0.99924795250423, 0.9990482215818578, 0.9988250086459504,
    0.9985783189429907, 0.9983081582712682, 0.9980145329807433,
    0.9976974499728977, 0.9973569167005722, 0.996992941167792,
    0.9966055319295779, 0.9961946980917455, 0.9957604493106914,
    0.9953027957931658, 0.9948217482960331, 0.9943173181260184,
    0.9937895171394426, 0.993238357741943, 0.9926638528881819,
    0.9920660160815423, 0.9914448613738105, 0.9908004033648453,
    0.9901326572022359, 0.9894416385809446, 0.9887273637429388,
    0.987989849476809, 0.987229113117374, 0.9864451725452739,
    0.9856380461865492, 0.984807753012208, 0.9839543125377807,
    0.98307774482286, 0.9821780704706307, 0.9812553106273847,
    0.9803094869820241, 0.9793406217655516, 0.9783487377505476,
    0.9773338582506356, 0.9762960071199334, 0.9752352087524931,
    0.9741514880817276, 0.9730448705798238, 0.9719153822571455,
    0.9707630496616201, 0.969587899878116, 0.9683899605278059,
    0.9671692597675166, 0.9659258262890683, 0.9646596893185995,
    0.9633708786158803, 0.9620594244736133, 0.9607253577167205,
    0.9593687097016202, 0.9579895123154889, 0.9565877979755123,
    0.9551635996281231, 0.9537169507482269, 0.9522478853384153,
    0.9507564379281666, 0.949242643573034, 0.9477065378538221,
    0.9461481568757505, 0.9445675372676048, 0.942964716180876,
    0.9413397312888873, 0.9396926207859084, 0.9380234233862579,
    0.9363321783233931, 0.9346189253489885, 0.9328837047320006,
    0.9311265572577219, 0.9293475242268225, 0.9275466474543786,
    0.9257239692688904, 0.9238795325112867, 0.9220133805339185,
    0.920125557199539, 0.918216106880274, 0.916285074456578,
    0.9143325053161794, 0.9123584453530141, 0.9103629409661467,
    0.9083460390586793, 0.90630778703665, 0.904248232807918,
    0.9021674247810377, 0.9000654118641213, 0.8979422434636883,
    0.8957979694835051, 0.8936326403234123, 0.8914463068781386,
    0.8892390205361062, 0.8870108331782218, 0.8847617971766579,
    0.8824919653936212, 0.8802013911801111, 0.8778901283746644,
    0.8755582313020909, 0.8732057547721958, 0.8708327540784921,
    0.8684392849969006, 0.8660254037844387, 0.8635911671778987,
    0.8611366323925138, 0.858661857120613, 0.8561668995302665,
    0.8536518182639163, 0.8511166724369997, 0.8485615216365591,
    0.8459864259198412, 0.8433914458128856, 0.8407766423091031,
    0.8381420768678404, 0.8354878114129364, 0.8328139083312672,
    0.8301204304712789, 0.8274074411415107, 0.8246750041091069,
    0.8219231835983182, 0.819152044288992, 0.8163616513150518,
    0.8135520702629675, 0.8107233671702123, 0.8078756085237112,
    0.8050088612582784, 0.802123192755044, 0.7992186708398695,
    0.7962953637817556, 0.7933533402912352, 0.7903926695187593,
    0.7874134210530723, 0.7844156649195758, 0.7813994715786824,
    0.7783649119241601, 0.775312057281466, 0.7722409794060693,
    0.769151750481765, 0.766044443118978, 0.7629191303530551,
    0.7597758856425494, 0.756614782867493, 0.7534358963276608,
    0.7502393007408243, 0.7470250712409959, 0.7437932833766611,
    0.7405440131090045, 0.7372773368101241, 0.7339933312612353,
    0.7306920736508675, 0.7273736415730488, 0.7240381130254827,
    0.7206855664077148, 0.7173160805192896, 0.713929734557899,
    0.710526608117521, 0.7071067811865476, 0.703670334145906,
    0.7002173477671687, 0.6967479032106549, 0.6932620820235241,
    0.6897599661378576, 0.6862416378687336, 0.6827071799122926,
    0.6791566753437933, 0.6755902076156604, 0.6720078605555225,
    0.6684097183642426, 0.6647958656139381, 0.6611663872459935,
    0.6575213685690636, 0.6538608952570697, 0.6501850533471835,
    0.6464939292378067, 0.6427876096865395, 0.6390661818081418,
    0.635329733072485, 0.6315783513024975, 0.6278121246720986,
    0.6240311417041269, 0.6202354912682602, 0.6164252625789255,
    0.612600545193203, 0.6087614290087209, 0.6049080042615419,
    0.6010403615240432, 0.5971585917027862, 0.593262786036382,
    0.5893530360933449, 0.5854294337699406, 0.5814920712880268,
    0.5775410411928852, 0.5735764363510459, 0.5695983499481064,
    0.5656068754865385, 0.5616021067834929, 0.5575841379685929,
    0.5535530634817224, 0.5495089780708062, 0.5454519767895827,
    0.5413821549953699, 0.5372996083468241, 0.5332044328016912,
    0.5290967246145525, 0.5249765803345602, 0.5208440968031698,
    0.516699371151863, 0.5125425007998654, 0.5083735834518555,
    0.5041927170956703, 0.49999999999999994, 0.49579553071207916,
    0.49157940805537065, 0.48735173112724245, 0.48311259929663863,
    0.4788621122017437, 0.47460036974764064, 0.47032747210396275,
    0.46604351970253877, 0.4617486132350339, 0.45744285365058085,
    0.4531263421534083, 0.44879918020046233, 0.4444614694990212,
    0.4401133120043047, 0.43575480991707927, 0.43138606568125343,
    0.4270071819814714, 0.4226182617406995, 0.4182194081178065,
    0.4138107245051393, 0.40939231452609276, 0.4049642820326738,
    0.40052673110306086, 0.3960797660391572, 0.39162349136413904,
    0.38715801182000065, 0.3826834323650899, 0.37819985817164264,
    0.3737073946233107, 0.3692061473126843, 0.36469622203881175,
    0.3601777248047104, 0.3556507618148765, 0.35111543947278884,
    0.34657186437840765, 0.3420201433256689, 0.3374603832999743,
    0.33289269147567685, 0.32831717521356135, 0.3237339420583214,
    0.31914309973603083, 0.3145447561516137, 0.30993901938630525,
    0.30532599769511326, 0.30070579950427334, 0.29607853340870016,
    0.2914443081694349, 0.2868032327110902, 0.28215541611928774,
    0.2775009676380958, 0.2728399966674611, 0.26817261276063753,
    0.263498925621611, 0.258819045102521, 0.2541330812010788,
    0.24944114405798165, 0.24474334395432376, 0.24003979130900596,
    0.2353305966761377, 0.23061587074244033, 0.225895724324645,
    0.22117026836688802, 0.21643961393810274, 0.21170387222941067,
    0.20696315455150538, 0.20221757233203796, 0.19746723711299763,
    0.19271226054808982, 0.18795275440011205, 0.18318883053832688,
    0.17842060093583242, 0.17364817766693072, 0.16887167290449276,
    0.16409119891732402, 0.15930686806752267, 0.15451879280784062,
    0.1497270856790398, 0.14493185930724697, 0.14013322640130613,
    0.135331299750131, 0.13052619222005157, 0.12571801675216274,
    0.12090688635966945, 0.11609291412523036, 0.11127621319829985,
    0.1064568967924685, 0.10163507818280217, 0.09681087070317945,
    0.09198438774362741, 0.0871557427476582, 0.08232504920959997,
    0.07749242067193107, 0.07265797072261079, 0.0678218129924096,
    0.06298406115223781, 0.05814482891047573, 0.0533042300102982,
    0.04846237822700297, 0.04361938736533607, 0.038775371256816835,
    0.03393044375706242, 0.029084718743111644, 0.02423831011074843,
    0.01939133177182472, 0.014543897651583058, 0.009696121685978408,
    0.004848117819001927, 12246467991473532e-32, -0.004848117819001238,
    -0.009696121685978163, -0.01454389765158237, -0.019391331771824474,
    -0.02423831011074774, -0.029084718743111398, -0.03393044375706173,
    -0.03877537125681659, -0.04361938736533583, -0.048462378227003174,
    -0.05330423001029795, -0.05814482891047593, -0.06298406115223758,
    -0.06782181299240934, -0.07265797072261056, -0.07749242067193128,
    -0.08232504920959974, -0.08715574274765794, -0.09198438774362716,
    -0.09681087070317876, -0.10163507818280193, -0.10645689679246781,
    -0.1112762131982996, -0.11609291412523012, -0.12090688635966965,
    -0.1257180167521625, -0.13052619222005177, -0.13533129975013078,
    -0.14013322640130632, -0.14493185930724675, -0.14972708567904,
    -0.1545187928078404, -0.15930686806752198, -0.16409119891732377,
    -0.16887167290449254, -0.17364817766693047, -0.17842060093583176,
    -0.18318883053832663, -0.1879527544001114, -0.1927122605480896,
    -0.19746723711299738, -0.20221757233203816, -0.20696315455150513,
    -0.21170387222941087, -0.21643961393810252, -0.2211702683668878,
    -0.22589572432464475, -0.23061587074244053, -0.23533059667613745,
    -0.2400397913090053, -0.2447433439543235, -0.24944114405798098,
    -0.2541330812010786, -0.25881904510252035, -0.2634989256216107,
    -0.26817261276063686, -0.2728399966674609, -0.27750096763809556,
    -0.2821554161192879, -0.28680323271108993, -0.29144430816943506,
    -0.29607853340869994, -0.30070579950427306, -0.30532599769511304,
    -0.3099390193863046, -0.3145447561516135, -0.3191430997360306,
    -0.3237339420583211, -0.3283171752135607, -0.33289269147567657,
    -0.3374603832999737, -0.34202014332566866, -0.3465718643784074,
    -0.35111543947278906, -0.35565076181487626, -0.36017772480471055,
    -0.3646962220388115, -0.3692061473126845, -0.3737073946233105,
    -0.3781998581716428, -0.38268343236508967, -0.38715801182000004,
    -0.3916234913641388, -0.39607976603915657, -0.40052673110306064,
    -0.4049642820326732, -0.40939231452609254, -0.41381072450513867,
    -0.4182194081178062, -0.4226182617406993, -0.4270071819814716,
    -0.4313860656812532, -0.43575480991707943, -0.4401133120043045,
    -0.444461469499021, -0.4487991802004621, -0.4531263421534085,
    -0.4574428536505806, -0.46174861323503374, -0.46604351970253854,
    -0.47032747210396214, -0.4746003697476404, -0.47886211220174313,
    -0.4831125992966384, -0.4873517311272422, -0.4915794080553708,
    -0.49579553071207894, -0.5000000000000001, -0.50419271709567,
    -0.5083735834518556, -0.5125425007998652, -0.5166993711518633,
    -0.5208440968031696, -0.5249765803345596, -0.5290967246145523,
    -0.533204432801691, -0.5372996083468239, -0.5413821549953693,
    -0.5454519767895825, -0.5495089780708056, -0.5535530634817222,
    -0.5575841379685926, -0.5616021067834931, -0.5656068754865384,
    -0.5695983499481065, -0.5735764363510458, -0.577541041192885,
    -0.5814920712880266, -0.5854294337699408, -0.5893530360933448,
    -0.5932627860363815, -0.597158591702786, -0.6010403615240426,
    -0.6049080042615417, -0.6087614290087203, -0.6126005451932028,
    -0.6164252625789249, -0.6202354912682599, -0.6240311417041268,
    -0.6278121246720987, -0.6315783513024973, -0.6353297330724852,
    -0.6390661818081416, -0.6427876096865393, -0.6464939292378065,
    -0.6501850533471829, -0.6538608952570695, -0.6575213685690635,
    -0.6611663872459933, -0.6647958656139376, -0.6684097183642425,
    -0.6720078605555221, -0.6755902076156601, -0.6791566753437931,
    -0.6827071799122927, -0.6862416378687334, -0.6897599661378577,
    -0.693262082023524, -0.696747903210655, -0.7002173477671685,
    -0.7036703341459061, -0.7071067811865475, -0.7105266081175206,
    -0.7139297345578989, -0.7173160805192892, -0.7206855664077146,
    -0.7240381130254823, -0.7273736415730487, -0.7306920736508671,
    -0.7339933312612352, -0.737277336810124, -0.7405440131090048,
    -0.743793283376661, -0.747025071240996, -0.7502393007408242,
    -0.7534358963276607, -0.7566147828674927, -0.7597758856425493,
    -0.7629191303530554, -0.7660444431189779, -0.7691517504817651,
    -0.7722409794060688, -0.7753120572814659, -0.7783649119241597,
    -0.7813994715786822, -0.7844156649195754, -0.7874134210530722,
    -0.7903926695187589, -0.7933533402912349, -0.7962953637817558,
    -0.79921867083987, -0.8021231927550437, -0.8050088612582785,
    -0.8078756085237111, -0.8107233671702119, -0.8135520702629674,
    -0.8163616513150515, -0.8191520442889916, -0.8219231835983181,
    -0.8246750041091064, -0.8274074411415104, -0.830120430471279,
    -0.8328139083312671, -0.8354878114129365, -0.8381420768678401,
    -0.8407766423091032, -0.8433914458128855, -0.8459864259198411,
    -0.8485615216365587, -0.8511166724369996, -0.8536518182639165,
    -0.8561668995302664, -0.8586618571206132, -0.8611366323925135,
    -0.8635911671778986, -0.8660254037844385, -0.8684392849969005,
    -0.8708327540784918, -0.8732057547721956, -0.8755582313020905,
    -0.8778901283746643, -0.8802013911801112, -0.8824919653936215,
    -0.8847617971766578, -0.8870108331782218, -0.889239020536106,
    -0.8914463068781383, -0.8936326403234122, -0.8957979694835049,
    -0.897942243463688, -0.9000654118641208, -0.9021674247810375,
    -0.9042482328079179, -0.90630778703665, -0.9083460390586792,
    -0.9103629409661468, -0.912358445353014, -0.9143325053161795,
    -0.9162850744565778, -0.918216106880274, -0.9201255571995388,
    -0.9220133805339183, -0.9238795325112865, -0.9257239692688903,
    -0.9275466474543786, -0.9293475242268223, -0.9311265572577219,
    -0.9328837047320003, -0.9346189253489884, -0.9363321783233929,
    -0.9380234233862578, -0.9396926207859082, -0.9413397312888873,
    -0.9429647161808761, -0.9445675372676049, -0.9461481568757504,
    -0.9477065378538222, -0.9492426435730339, -0.9507564379281666,
    -0.9522478853384153, -0.9537169507482267, -0.9551635996281229,
    -0.956587797975512, -0.9579895123154888, -0.9593687097016201,
    -0.9607253577167205, -0.9620594244736131, -0.9633708786158804,
    -0.9646596893185994, -0.9659258262890683, -0.9671692597675166,
    -0.9683899605278059, -0.9695878998781159, -0.97076304966162,
    -0.9719153822571452, -0.9730448705798238, -0.9741514880817276,
    -0.975235208752493, -0.9762960071199334, -0.9773338582506355,
    -0.9783487377505475, -0.9793406217655514, -0.980309486982024,
    -0.9812553106273846, -0.9821780704706307, -0.98307774482286,
    -0.9839543125377805, -0.984807753012208, -0.9856380461865493,
    -0.9864451725452739, -0.9872291131173742, -0.9879898494768089,
    -0.9887273637429387, -0.9894416385809445, -0.9901326572022358,
    -0.9908004033648452, -0.9914448613738104, -0.9920660160815423,
    -0.9926638528881818, -0.993238357741943, -0.9937895171394426,
    -0.9943173181260184, -0.994821748296033, -0.9953027957931658,
    -0.9957604493106913, -0.9961946980917455, -0.9966055319295779,
    -0.996992941167792, -0.9973569167005722, -0.9976974499728977,
    -0.9980145329807433, -0.9983081582712682, -0.9985783189429907,
    -0.9988250086459504, -0.9990482215818578, -0.99924795250423,
    -0.9994241967185149, -0.9995769500822006, -0.9997062090049132,
    -0.9998119704485015, -0.9998942319271076, -0.9999529915072262,
    -0.9999882478077495, -1, -0.9999882478077495, -0.9999529915072262,
    -0.9998942319271076, -0.9998119704485015, -0.9997062090049132,
    -0.9995769500822006, -0.9994241967185149, -0.99924795250423,
    -0.9990482215818578, -0.9988250086459504, -0.9985783189429907,
    -0.9983081582712682, -0.9980145329807433, -0.9976974499728977,
    -0.9973569167005724, -0.996992941167792, -0.9966055319295779,
    -0.9961946980917455, -0.9957604493106914, -0.9953027957931658,
    -0.9948217482960331, -0.9943173181260185, -0.9937895171394426,
    -0.993238357741943, -0.9926638528881819, -0.9920660160815424,
    -0.9914448613738105, -0.9908004033648453, -0.9901326572022358,
    -0.9894416385809446, -0.9887273637429387, -0.987989849476809,
    -0.9872291131173742, -0.986445172545274, -0.9856380461865493,
    -0.9848077530122081, -0.9839543125377807, -0.9830777448228601,
    -0.9821780704706308, -0.9812553106273846, -0.9803094869820241,
    -0.9793406217655515, -0.9783487377505476, -0.9773338582506355,
    -0.9762960071199335, -0.9752352087524931, -0.9741514880817276,
    -0.9730448705798239, -0.9719153822571454, -0.9707630496616201,
    -0.969587899878116, -0.968389960527806, -0.9671692597675167,
    -0.9659258262890684, -0.9646596893185995, -0.9633708786158806,
    -0.9620594244736133, -0.9607253577167206, -0.9593687097016202,
    -0.9579895123154889, -0.9565877979755121, -0.955163599628123,
    -0.9537169507482268, -0.9522478853384154, -0.9507564379281668,
    -0.949242643573034, -0.9477065378538223, -0.9461481568757506,
    -0.944567537267605, -0.9429647161808762, -0.9413397312888874,
    -0.9396926207859083, -0.9380234233862579, -0.936332178323393,
    -0.9346189253489885, -0.9328837047320004, -0.9311265572577221,
    -0.9293475242268224, -0.9275466474543788, -0.9257239692688904,
    -0.9238795325112866, -0.9220133805339186, -0.9201255571995389,
    -0.9182161068802742, -0.9162850744565779, -0.9143325053161796,
    -0.9123584453530141, -0.9103629409661469, -0.9083460390586794,
    -0.9063077870366503, -0.9042482328079181, -0.9021674247810376,
    -0.9000654118641209, -0.8979422434636882, -0.895797969483505,
    -0.8936326403234123, -0.8914463068781384, -0.8892390205361063,
    -0.887010833178222, -0.8847617971766579, -0.8824919653936216,
    -0.8802013911801113, -0.8778901283746645, -0.8755582313020907,
    -0.8732057547721959, -0.870832754078492, -0.8684392849969007,
    -0.8660254037844386, -0.8635911671778989, -0.8611366323925137,
    -0.8586618571206134, -0.8561668995302666, -0.8536518182639167,
    -0.8511166724369998, -0.848561521636559, -0.8459864259198413,
    -0.8433914458128857, -0.8407766423091034, -0.8381420768678404,
    -0.8354878114129367, -0.8328139083312672, -0.8301204304712791,
    -0.8274074411415107, -0.8246750041091067, -0.8219231835983183,
    -0.8191520442889918, -0.8163616513150517, -0.8135520702629676,
    -0.8107233671702121, -0.8078756085237113, -0.8050088612582788,
    -0.802123192755044, -0.7992186708398701, -0.796295363781756,
    -0.7933533402912352, -0.7903926695187591, -0.7874134210530724,
    -0.7844156649195756, -0.7813994715786825, -0.7783649119241599,
    -0.7753120572814661, -0.7722409794060691, -0.7691517504817653,
    -0.7660444431189781, -0.7629191303530556, -0.7597758856425495,
    -0.7566147828674927, -0.753435896327661, -0.7502393007408246,
    -0.7470250712409963, -0.7437932833766612, -0.740544013109005,
    -0.7372773368101242, -0.7339933312612357, -0.7306920736508676,
    -0.7273736415730492, -0.7240381130254828, -0.7206855664077145,
    -0.7173160805192891, -0.7139297345578991, -0.7105266081175208,
    -0.7071067811865477, -0.7036703341459063, -0.7002173477671687,
    -0.6967479032106556, -0.6932620820235246, -0.6897599661378577,
    -0.6862416378687334, -0.6827071799122926, -0.679156675343793,
    -0.6755902076156605, -0.6720078605555223, -0.6684097183642427,
    -0.6647958656139378, -0.6611663872459935, -0.6575213685690637,
    -0.6538608952570701, -0.6501850533471836, -0.6464939292378064,
    -0.6427876096865396, -0.6390661818081416, -0.6353297330724854,
    -0.6315783513024976, -0.627812124672099, -0.624031141704127,
    -0.6202354912682606, -0.6164252625789255, -0.6126005451932034,
    -0.6087614290087209, -0.6049080042615417, -0.6010403615240425,
    -0.5971585917027863, -0.5932627860363818, -0.589353036093345,
    -0.585429433769941, -0.5814920712880269, -0.5775410411928856,
    -0.5735764363510465, -0.5695983499481065, -0.5656068754865391,
    -0.561602106783493, -0.5575841379685926, -0.5535530634817225,
    -0.5495089780708059, -0.5454519767895828, -0.5413821549953696,
    -0.5372996083468242, -0.5332044328016913, -0.5290967246145529,
    -0.5249765803345603, -0.5208440968031696, -0.5166993711518632,
    -0.5125425007998651, -0.5083735834518559, -0.5041927170956704,
    -0.5000000000000004, -0.49579553071207927, -0.49157940805537115,
    -0.48735173112724256, -0.48311259929663913, -0.4788621122017438,
    -0.47460036974764036, -0.4703274721039621, -0.4660435197025389,
    -0.46174861323503363, -0.45744285365058096, -0.4531263421534088,
    -0.44879918020046244, -0.4444614694990217, -0.4401133120043052,
    -0.43575480991708015, -0.4313860656812539, -0.42700718198147153,
    -0.4226182617406992, -0.4182194081178066, -0.413810724505139,
    -0.40939231452609287, -0.40496428203267354, -0.400526731103061,
    -0.3960797660391569, -0.39162349136413954, -0.38715801182000076,
    -0.3826834323650904, -0.37819985817164276, -0.3737073946233104,
    -0.3692061473126848, -0.36469622203881186, -0.3601777248047109,
    -0.3556507618148766, -0.3511154394727894, -0.34657186437840776,
    -0.34202014332566943, -0.3374603832999744, -0.3328926914756765,
    -0.32831717521356063, -0.32373394205832107, -0.31914309973603056,
    -0.3145447561516138, -0.3099390193863049, -0.30532599769511337,
    -0.30070579950427384, -0.2960785334087003, -0.29144430816943584,
    -0.2868032327110907, -0.28215541611928785, -0.2775009676380955,
    -0.2728399966674612, -0.2681726127606372, -0.2634989256216111,
    -0.2588190451025207, -0.2541330812010789, -0.24944114405798135,
    -0.24474334395432432, -0.24003979130900607, -0.23533059667613823,
    -0.23061587074244044, -0.2258957243246447, -0.22117026836688813,
    -0.21643961393810288, -0.21170387222941123, -0.2069631545515055,
    -0.20221757233203852, -0.19746723711299774, -0.19271226054809037,
    -0.1879527544001122, -0.18318883053832655, -0.17842060093583256,
    -0.1736481776669304, -0.16887167290449245, -0.16409119891732413,
    -0.15930686806752234, -0.15451879280784075, -0.14972708567904036,
    -0.1449318593072471, -0.14013322640130713, -0.13533129975013158,
    -0.13052619222005168, -0.1257180167521624, -0.12090688635966958,
    -0.11609291412523004, -0.11127621319829996, -0.10645689679246818,
    -0.10163507818280229, -0.09681087070317913, -0.09198438774362797,
    -0.08715574274765832, -0.08232504920960054, -0.0774924206719312,
    -0.07265797072261047, -0.06782181299240972, -0.06298406115223794,
    -0.0581448289104763, -0.05330423001029832, -0.04846237822700354,
    -0.043619387365336194, -0.038775371256817404, -0.03393044375706254,
    -0.02908471874311221, -0.02423831011074855, -0.019391331771824397,
    -0.014543897651582293, -0.009696121685978531, -0.004848117819001606,
  ];

  static reverseSinTableLookup(value: number, start: number, end: number, reverse: boolean): number {
    while (start <= end) {
      const mid = Math.floor((start + end) / 2);
      const midValue = this.SIN_TABLE[mid];

      if (midValue === value) return mid;

      if (reverse ? value < midValue : midValue < value) {
        start = mid + 1;
      } else {
        end = mid - 1;
      }
    }

    return Math.abs(value - this.SIN_TABLE[start]) < Math.abs(value - this.SIN_TABLE[end])
      ? start
      : end;
  }

  static pow(base: number, exponent: number): number {
    if (!Number.isFinite(base) || !Number.isFinite(exponent) ||
      (Number.isSafeInteger(base) && Number.isSafeInteger(exponent))) {
      return base ** exponent;
    }

    if (!Number.isSafeInteger(exponent)) {
      throw new Error("Exponent must be a safe integer");
    }

    return Math.floor(base * this.EXP_10_PRECISION) ** exponent /
      this.EXP_10_PRECISION ** exponent;
  }

  static sqrt(value: number): number {
    if (value === 0) return 0;

    let prev;
    let result = value / 3;

    while (Math.abs((prev = result) - (result = (value / result + result) / 2)) > 5e-15);

    return result;
  }

  static sin(angle: number): number {
    if (!Number.isFinite(angle)) return NaN;
    if (!angle) return angle;

    const normalized = angle / (2 * Math.PI) - Math.floor(angle / (2 * Math.PI));
    const index = Math.floor(normalized * this.SIN_TABLE.length);

    return this.SIN_TABLE[index];
  }

  static cos(angle: number): number {
    return this.sin(angle + Math.PI / 2);
  }

  static asin(value: number): number {
    if (!isBetween(value, -1, 1)) return NaN;
    if (!value) return 0;

    const tableLength = this.SIN_TABLE.length;

    return value > 0
      ? (2 * Math.PI * this.reverseSinTableLookup(value, 0, tableLength / 4, false)) / tableLength
      : Math.PI - (2 * Math.PI * this.reverseSinTableLookup(value, tableLength / 2, 0.75 * tableLength, true)) / tableLength;
  }

  static acos(value: number): number {
    return Math.PI / 2 - this.asin(value);
  }

  static atan2(y: number, x: number): number {
    if (Number.isNaN(x) || Number.isNaN(y)) return NaN;

    if (Number.isFinite(y) || Number.isFinite(x)) {
      if (Number.isFinite(x) && x !== 0) {
        if (Number.isFinite(y) && y !== 0) {
          return this.atan2FiniteNonZero(y, x);
        }
        return this.signIncZero(y) * Math.PI * 0.5;
      }
      return this.signIncZero(y) * (this.signIncZero(x) < 0 ? Math.PI : 0);
    }

    return Math.sign(y) * Math.PI * (Math.sign(x) > 0 ? 0.25 : 0.75);
  }

  static atan2FiniteNonZero(y: number, x: number): number {
    const absX = Math.abs(x);
    const absY = Math.abs(y);
    const ratio = Math.min(absX, absY) / Math.max(absX, absY);
    const ratioSquared = ratio * ratio;

    let result = ((-0.0464964749 * ratioSquared + 0.15931422) * ratioSquared - 0.327622764) * ratioSquared * ratio + ratio;

    if (absX < absY) result = Math.PI / 2 - result;
    if (x < 0) result = Math.PI - result;
    if (y < 0) result = -result;

    return result;
  }

  static signIncZero(value: number): number {
    return value === -Infinity || 1 / value < 0 ? -1 : 1;
  }
}
